Avastage optimistlike uuenduste ja konfliktide lahendamise keerukusi, kasutades Reacti useOptimistic konksu. Õppige, kuidas ühendada vastuolulisi uuendusi ning luua vastupidavaid ja reageerivaid kasutajaliideseid. Globaalne juhend arendajatele.
React useOptimistic konfliktide lahendamine: optimistlike uuenduste ĂĽhendamise loogika valdamine
Veebiarenduse dünaamilises maailmas on sujuva ja reageeriva kasutajakogemuse pakkumine esmatähtis. Üks võimas tehnika, mis annab arendajatele selle saavutamiseks võimaluse, on optimistlikud uuendused. See lähenemine võimaldab kasutajaliidesel (UI) koheselt uueneda, isegi enne kui server on muudatusi kinnitanud. See loob illusiooni kohesest tagasisidest, muutes rakenduse kiiremaks ja sujuvamaks. Kuid optimistlike uuenduste olemus nõuab tugevat strateegiat võimalike konfliktide käsitlemiseks, kus tuleb mängu ühendamise loogika. See blogipostitus süveneb optimistlikesse uuendustesse, konfliktide lahendamisse ja Reacti `useOptimistic` konksu kasutamisse, pakkudes põhjalikku juhendit arendajatele üle maailma.
Optimistlike uuenduste mõistmine
Optimistlikud uuendused tähendavad sisuliselt seda, et kasutajaliidest uuendatakse enne, kui serverist on kinnitus saadud. Kujutage ette, et kasutaja klõpsab sotsiaalmeedia postitusel 'meeldib' nuppu. Optimistliku uuenduse korral peegeldab kasutajaliides kohe 'meeldimist', näidates suurenenud meeldimiste arvu, ootamata serveri vastust. See parandab oluliselt kasutajakogemust, kõrvaldades tajutava latentsuse.
Eelised on selged:
- Parem kasutajakogemus: Kasutajad tajuvad rakendust kiirema ja reageerivamana.
- Vähenenud tajutav latentsus: Kohene tagasiside varjab võrguviivitusi.
- Suurenenud kaasatus: Kiiremad interaktsioonid soodustavad kasutajate kaasamist.
Kuid mündi teine pool on konfliktide potentsiaal. Kui serveri olek erineb optimistlikust kasutajaliidese uuendusest, näiteks kui teine kasutaja samal ajal sama postitust 'meeldivaks' märgib, tekib konflikt. Nende konfliktide lahendamine nõuab ühendamise loogika hoolikat kaalumist.
Konfliktide probleem
Optimistlike uuenduste konfliktid tekivad siis, kui serveri olek erineb kliendi optimistlikest eeldustest. See on eriti levinud koostöörakendustes või keskkondades, kus kasutajad tegutsevad samaaegselt. Mõelgem stsenaariumile kahe kasutajaga, Kasutaja A ja Kasutaja B, kes mõlemad üritavad samaaegselt samu andmeid uuendada.
Näidisstsenaarium:
- Algne olek: Jagatud loendur on lähtestatud väärtusele 0.
- Kasutaja A tegevus: Kasutaja A klõpsab nupul 'Suurenda', käivitades optimistliku uuenduse (loendur näitab nüüd 1) ja saates päringu serverile.
- Kasutaja B tegevus: Samaaegselt klõpsab ka Kasutaja B nupul 'Suurenda', käivitades oma optimistliku uuenduse (loendur näitab nüüd 1) ja saates päringu serverile.
- Serveri töötlemine: Server võtab vastu mõlemad suurendamise päringud.
- Konflikt: Ilma korrektse käsitlemiseta võib serveri lõplik olek valesti kajastada ainult ühte suurendamist (loendur väärtusel 1), mitte oodatud kahte (loendur väärtusel 2).
See rõhutab vajadust strateegiate järele, et lepitada lahknevusi kliendi optimistliku oleku ja serveri tegeliku oleku vahel.
Konfliktide lahendamise strateegiad
Konfliktide lahendamiseks ja andmete järjepidevuse tagamiseks saab kasutada mitmeid tehnikaid:
1. Serveripoolne konfliktide tuvastamine ja lahendamine
Server mängib konfliktide tuvastamisel ja lahendamisel kriitilist rolli. Levinud lähenemisviisid hõlmavad:
- Optimistlik lukustamine: Server kontrollib, kas andmeid on muudetud pärast seda, kui klient need kätte sai. Kui on, lükatakse uuendus tagasi või ühendatakse, tavaliselt versiooninumbri või ajatempli abil.
- Pessimistlik lukustamine: Server lukustab andmed uuendamise ajaks, vältides samaaegseid muudatusi. See lihtsustab konfliktide lahendamist, kuid võib vähendada samaaegsust ja aeglustada jõudlust.
- Viimane kirjutaja võidab (Last-Write-Wins): Viimast serverisse saabunud uuendust peetakse autoriteetseks, mis võib hooletu rakendamise korral põhjustada andmete kadu.
- Ühendamisstrateegiad: Keerukamad lähenemised võivad hõlmata kliendi uuenduste ühendamist serveris, sõltuvalt andmete olemusest ja konkreetsest konfliktist. Näiteks suurendamise operatsiooni puhul saab server lihtsalt liita kliendi muudatuse praegusele väärtusele, olenemata olekust.
2. Kliendipoolne konfliktide lahendamine ĂĽhendamise loogikaga
Kliendipoolne ühendamise loogika on sujuva kasutajakogemuse tagamiseks ja kohese tagasiside andmiseks ülioluline. See ennetab konflikte ja püüab neid sujuvalt lahendada. See lähenemine hõlmab kliendi optimistliku uuenduse ühendamist serveri kinnitatud uuendusega.
Siin võib Reacti `useOptimistic` konks olla hindamatu väärtusega. Konks võimaldab teil hallata optimistlikke oleku uuendusi ja pakkuda mehhanisme serveri vastuste käsitlemiseks. See annab võimaluse taastada kasutajaliides teadaolevale olekule või teostada uuenduste ühendamine.
3. Ajatemplite või versioonimise kasutamine
Ajatemplite või versiooninumbrite lisamine andmete uuendustesse võimaldab kliendil ja serveril muudatusi jälgida ja konflikte hõlpsasti lahendada. Klient saab võrrelda serveri andmeversiooni enda omaga ja otsustada parima tegevuskäigu üle (nt rakendada serveri muudatused, ühendada muudatused või paluda kasutajal konflikt lahendada).
4. Operatsioonilised teisendused (OT)
OT on keerukas tehnika, mida kasutatakse koostöös redigeerimise rakendustes, võimaldades kasutajatel sama dokumenti samaaegselt ilma konfliktideta redigeerida. Iga muudatus esitatakse operatsioonina, mida saab teiste operatsioonide suhtes teisendada, tagades, et kõik kliendid jõuavad sama lõppolekuni. See on eriti kasulik rikastekstiredaktorites ja sarnastes reaalajas koostöövahendites.
Reacti `useOptimistic` konksu tutvustus
Reacti `useOptimistic` konks pakub õigesti rakendatuna sujuvamat viisi optimistlike uuenduste haldamiseks ja konfliktide lahendamise strateegiate integreerimiseks. See võimaldab teil:
- Hallata optimistlikku olekut: Hoida optimistlikku olekut koos tegeliku olekuga.
- Käivitada uuendusi: Määratleda, kuidas kasutajaliides optimistlikult muutub.
- Käidelda serveri vastuseid: Käidelda serveripoolse operatsiooni õnnestumist või ebaõnnestumist.
- Rakendada tagasivõtmise või ühendamise loogikat: Määratleda, kuidas taastada algne olek või ühendada muudatused, kui serveri vastus saabub.
`useOptimistic` konksu põhinäide
Siin on lihtne näide, mis illustreerib põhimõistet:
import React, { useState, useOptimistic } from 'react';
function Counter() {
const [count, setOptimisticCount] = useOptimistic(
0, // Initial state
(state, optimisticValue) => {
// Merge logic: returns the optimistic value
return optimisticValue;
}
);
const [isUpdating, setIsUpdating] = useState(false);
const handleIncrement = async () => {
const optimisticValue = count + 1;
setOptimisticCount(optimisticValue);
setIsUpdating(true);
try {
// Simulate an API call
await new Promise(resolve => setTimeout(resolve, 1000));
// On success, no special action needed, state is already updated.
} catch (error) {
// Handle failure, potentially rollback or show an error.
setOptimisticCount(count); // Revert to previous state on failure.
console.error('Increment failed:', error);
} finally {
setIsUpdating(false);
}
};
return (
Count: {count}
);
}
export default Counter;
Selgitus:
- `useOptimistic(0, ...)`: Me lähtestame oleku väärtusega `0` ja anname edasi funktsiooni, mis tegeleb optimistliku uuenduse/ühendamisega.
- `optimisticValue`: Funktsiooni `handleIncrement` sees, kui nuppu klõpsatakse, arvutame optimistliku väärtuse ja kutsume välja `setOptimisticCount(optimisticValue)`, mis uuendab koheselt kasutajaliidest.
- `setIsUpdating(true)`: Annab kasutajale teada, et uuendus on pooleli.
- `try...catch...finally`: Simuleerib API-kutset, demonstreerides, kuidas käsitleda serveri õnnestumist või ebaõnnestumist.
- Õnnestumine: Eduka vastuse korral säilitatakse optimistlik uuendus.
- Ebaõnnestumine: Ebaõnnestumise korral taastame selles näites oleku eelmisele väärtusele (`setOptimisticCount(count)`). Alternatiivina võiksime kuvada veateate või rakendada keerukamat ühendamisloogikat.
- `mergeFn`: Teine parameeter `useOptimistic` konksus on kriitilise tähtsusega. See on funktsioon, mis tegeleb sellega, kuidas oleku muutumisel ühendada/uuendada.
Keeruka ĂĽhendamisloogika rakendamine `useOptimistic` konksuga
`useOptimistic` konksu teine argument, ühendamisfunktsioon, pakub võtit keerukate konfliktide lahendamiseks. See funktsioon vastutab optimistliku oleku kombineerimise eest tegeliku serveri olekuga. See saab kaks parameetrit: praeguse oleku ja optimistliku väärtuse (väärtus, mille kasutaja on just sisestanud/muutnud). Funktsioon peab tagastama uue oleku, mis rakendatakse.
Vaatame veel näiteid:
1. Loenduri suurendamine kinnitusega (vastupidavam)
Tuginedes põhilisele loenduri näitele, tutvustame kinnitussüsteemi, mis võimaldab kasutajaliidesel naasta eelmise väärtuse juurde, kui server tagastab vea. Täiustame näidet serveri kinnitusega.
import React, { useState, useOptimistic } from 'react';
function Counter() {
const [count, setOptimisticCount] = useOptimistic(
0, // Initial state
(state, optimisticValue) => {
// Merge logic - updates the count to the optimistic value
return optimisticValue;
}
);
const [isUpdating, setIsUpdating] = useState(false);
const [lastServerCount, setLastServerCount] = useState(0);
const handleIncrement = async () => {
const optimisticValue = count + 1;
setOptimisticCount(optimisticValue);
setIsUpdating(true);
try {
// Simulate an API call
const response = await fetch('/api/increment', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ count: optimisticValue }),
});
const data = await response.json();
if (data.success) {
setLastServerCount(data.count) //Optional to verify. Otherwise can remove the state.
}
else {
setOptimisticCount(count) // Revert the optimistic update
}
} catch (error) {
// Revert on error
setOptimisticCount(count);
console.error('Increment failed:', error);
} finally {
setIsUpdating(false);
}
};
return (
Count: {count} (Last Server Count: {lastServerCount})
);
}
export default Counter;
Põhilised täiustused:
- Serveri kinnitus: `fetch` päring aadressile `/api/increment` simuleerib serverikutset loenduri suurendamiseks.
- Veakäsitlus: `try...catch` plokk käsitleb sujuvalt võimalikke võrguvigu või serveripoolseid tõrkeid. Kui API-kutse ebaõnnestub (nt võrguviga, serveri viga), võetakse optimistlik uuendus tagasi, kasutades `setOptimisticCount(count)`.
- Serveri vastuse kontrollimine (valikuline): Reaalses rakenduses tagastaks server tõenäoliselt vastuse, mis sisaldab uuendatud loenduri väärtust. Selles näites kontrollime pärast suurendamist serveri vastust (data.success).
2. Nimekirja uuendamine (optimistlik lisamine/eemaldamine)
Uurime näidet elementide nimekirja haldamisest, võimaldades optimistlikke lisamisi ja eemaldamisi. See näitab, kuidas ühendada lisamisi ja eemaldamisi ning tegeleda serveri vastusega.
import React, { useState, useOptimistic } from 'react';
function ItemList() {
const [items, setItems] = useState([{
id: 1,
text: 'Item 1'
}]); // initial state
const [optimisticItems, setOptimisticItems] = useOptimistic(
items, //Initial state
(state, optimisticValue) => {
//Merge logic - replaces the current state
return optimisticValue;
}
);
const [isAdding, setIsAdding] = useState(false);
const [isRemoving, setIsRemoving] = useState(false);
const handleAddItem = async () => {
const newItem = {
id: Math.random(),
text: 'New Item',
optimistic: true, // Mark as optimistic
};
const optimisticList = [...optimisticItems, newItem];
setOptimisticItems(optimisticList);
setIsAdding(true);
try {
//Simulate API call to add to the server.
await new Promise(resolve => setTimeout(resolve, 1000));
//Update the list when the server acknowledges it (remove the 'optimistic' flag)
const confirmedItems = optimisticList.map(item => {
if (item.optimistic) {
return { ...item, optimistic: false }
}
return item;
})
setItems(confirmedItems);
} catch (error) {
//Rollback - Remove the optimistic item on error
const rolledBackItems = optimisticItems.filter(item => !item.optimistic);
setOptimisticItems(rolledBackItems);
} finally {
setIsAdding(false);
}
};
const handleRemoveItem = async (itemId) => {
const optimisticList = optimisticItems.filter(item => item.id !== itemId);
setOptimisticItems(optimisticList);
setIsRemoving(true);
try {
//Simulate API call to remove the item from the server.
await new Promise(resolve => setTimeout(resolve, 1000));
//No special action here. Items are removed from the UI optimistically.
} catch (error) {
//Rollback - Re-add the item if the removal fails.
//Note, the real item could have changed in the server.
//A more robust solution would require a server state check.
//But this simple example works.
const itemToRestore = items.find(item => item.id === itemId);
if (itemToRestore) {
setOptimisticItems([...optimisticItems, itemToRestore]);
}
// Alternatively, fetch the latest items to re-sync
} finally {
setIsRemoving(false);
}
};
return (
{optimisticItems.map(item => (
-
{item.text} - {
item.optimistic ? 'Adding...' : 'Confirmed'
}
))}
);
}
export default ItemList;
Selgitus:
- Algne olek: Lähtestab elementide nimekirja.
- `useOptimistic` integratsioon: Kasutame `useOptimistic` konksu elementide nimekirja optimistliku oleku haldamiseks.
- Elementide lisamine: Kui kasutaja lisab elemendi, loome uue elemendi, mille `optimistic` lipp on seatud väärtusele `true`. See võimaldab meil optimistlikke muudatusi visuaalselt eristada. Element lisatakse kohe nimekirja, kasutades `setOptimisticItems`. Kui server vastab edukalt, uuendame nimekirja olekus. Kui serverikutse ebaõnnestub, eemaldame elemendi.
- Elementide eemaldamine: Kui kasutaja eemaldab elemendi, eemaldatakse see kohe `optimisticItems` hulgast. Kui server kinnitab, on kõik korras. Kui server ebaõnnestub, taastame elemendi nimekirja.
- Visuaalne tagasiside: Komponent renderdab elemente erineva stiiliga (`color: gray`), kui need on optimistlikus olekus (ootavad serveri kinnitust).
- Serveri simulatsioon: Näites olevad simuleeritud API-kutsed jäljendavad võrgupäringuid. Reaalses stsenaariumis tehtaks need päringud teie API otspunktidesse.
3. Muudetavad väljad: reasisene redigeerimine
Optimistlikud uuendused toimivad hästi ka reasisese redigeerimise stsenaariumides. Kasutajal lubatakse välja redigeerida ja me kuvame laadimisindikaatorit, kuni server saab kinnituse. Kui uuendus ebaõnnestub, lähtestame välja selle eelmisele väärtusele. Kui uuendus õnnestub, uuendame olekut.
import React, { useState, useOptimistic, useRef } from 'react';
function EditableField({ initialValue, onSave, isEditable = true }) {
const [value, setOptimisticValue] = useOptimistic(
initialValue,
(state, optimisticValue) => {
return optimisticValue;
}
);
const [isSaving, setIsSaving] = useState(false);
const [isEditing, setIsEditing] = useState(false);
const inputRef = useRef(null);
const handleEditClick = () => {
setIsEditing(true);
};
const handleSave = async () => {
if (!isEditable) return;
setIsSaving(true);
try {
await onSave(value);
} catch (error) {
console.error('Failed to save:', error);
//Rollback
setOptimisticValue(initialValue);
} finally {
setIsSaving(false);
setIsEditing(false);
}
};
const handleCancel = () => {
setOptimisticValue(initialValue);
setIsEditing(false);
};
return (
{isEditing ? (
setOptimisticValue(e.target.value)}
/>
) : (
{value}
)}
);
}
export default EditableField;
Selgitus:
- Komponent `EditableField`: See komponent võimaldab väärtuse reasisest redigeerimist.
- `useOptimistic` välja jaoks: `useOptimistic` hoiab silma peal väärtusel ja tehtaval muudatusel.
- Tagasikutse `onSave`: Atribuut `onSave` võtab vastu funktsiooni, mis tegeleb salvestamisprotsessiga.
- Redigeeri/Salvesta/Tühista: Komponent kuvab kas tekstivälja (redigeerimisel) või väärtuse enda (mitte redigeerimisel).
- Salvestamise olek: Salvestamise ajal kuvame teate „Salvestan...” ja keelame salvestamise nupu.
- Veakäsitlus: Kui `onSave` viskab vea, taastatakse väärtus `initialValue`-le.
Täiustatud ühendamisloogika kaalutlused
Eespool toodud näited annavad põhiteadmised optimistlikest uuendustest ja `useOptimistic` konksu kasutamisest. Reaalsed stsenaariumid nõuavad sageli keerukamat ühendamisloogikat. Siin on mõned täiustatud kaalutlused:
1. Samaaegsete uuenduste käsitlemine
Kui mitu kasutajat uuendab samaaegselt samu andmeid või ühel kasutajal on avatud mitu vahekaarti, on vaja hoolikalt kavandatud ühendamisloogikat. See võib hõlmata:
- Versioonikontroll: Versioonisüsteemi rakendamine muudatuste jälgimiseks ja konfliktide lahendamiseks.
- Optimistlik lukustamine: Kasutaja seansi optimistlik lukustamine, vältides vastuolulist uuendust.
- Konfliktide lahendamise algoritmid: Algoritmide kavandamine muudatuste automaatseks ühendamiseks, näiteks kõige uuema oleku ühendamine.
2. Konteksti ja olekuhaldusraamatukogude kasutamine
Keerukamate rakenduste puhul kaaluge konteksti ja olekuhaldusraamatukogude, nagu Redux või Zustand, kasutamist. Need raamatukogud pakuvad tsentraliseeritud hoidlat rakenduse oleku jaoks, mis teeb optimistlike uuenduste haldamise ja jagamise erinevate komponentide vahel lihtsamaks. Saate neid kasutada oma optimistlike uuenduste oleku järjepidevaks haldamiseks. Samuti võivad need hõlbustada keerukaid ühendamisoperatsioone, hallates võrgukutseid ja oleku uuendusi.
3. Jõudluse optimeerimine
Optimistlikud uuendused ei tohiks põhjustada jõudluse kitsaskohti. Pidage meeles järgmist:
- Optimeerige API-kutseid: Veenduge, et API-kutsed on tõhusad ega blokeeri kasutajaliidest.
- Debouncing ja Throttling: Kasutage debouncing- või throttling-tehnikaid uuenduste sageduse piiramiseks, eriti kiire kasutajasisestuse korral (nt tekstisisestus).
- Laadimine vajadusel (Lazy Loading): Laadige andmeid laisalt, et vältida kasutajaliidese ülekoormamist.
4. Veateavitus ja kasutaja tagasiside
Andke kasutajale selget ja informatiivset tagasisidet optimistlike uuenduste oleku kohta. See võib hõlmata:
- Laadimisindikaatorid: Kuvage API-kutsete ajal laadimisindikaatoreid.
- Veateated: Kuvage sobivaid veateateid, kui serveri uuendus ebaõnnestub. Veateated peaksid olema informatiivsed ja tegevusele suunavad, juhendades kasutajat probleemi lahendama.
- Visuaalsed vihjed: Kasutage visuaalseid vihjeid (nt nupu värvi muutmine) uuenduse oleku näitamiseks.
5. Testimine
Testige oma optimistlikke uuendusi ja ühendamisloogikat põhjalikult, et tagada andmete järjepidevus ja kasutajakogemuse säilimine kõigis stsenaariumides. See hõlmab nii optimistliku kliendipoolse käitumise kui ka serveripoolsete konfliktide lahendamise mehhanismide testimist.
`useOptimistic` konksu parimad praktikad
- Hoidke ühendamisfunktsioon lihtsana: Muutke oma ühendamisfunktsioon selgeks ja lühikeseks, et seda oleks lihtne mõista ja hooldada.
- Kasutage muutumatuid andmeid: Kasutage muutumatuid andmestruktuure, et tagada kasutajaliidese oleku muutumatus ning aidata kaasa silumisele ja etteaimatavusele.
- Käsitlege serveri vastuseid: Käsitlege korrektselt nii edukaid kui ka vigaseid serveri vastuseid.
- Andke selget tagasisidet: Suhelge kasutajaga operatsioonide oleku kohta.
- Testige põhjalikult: Testige kõiki stsenaariume, et tagada korrektne ühendamiskäitumine.
Reaalse maailma näited ja globaalsed rakendused
Optimistlikud uuendused ja `useOptimistic` on väärtuslikud paljudes rakendustes. Siin on mõned rahvusvahelise tähtsusega näited:
- Sotsiaalmeedia platvormid (nt Facebook, Twitter): Kohesed 'meeldib', kommenteerimise ja jagamise funktsioonid tuginevad sujuva kasutajakogemuse tagamiseks suuresti optimistlikele uuendustele.
- E-kaubanduse platvormid (nt Amazon, Alibaba): Ostukorvi lisamine, koguste uuendamine või tellimuste esitamine kasutavad sageli optimistlikke uuendusi.
- Koostöövahendid (nt Google Docs, Microsoft Office Online): Reaalajas dokumendi redigeerimine ja koostööfunktsioonid on sageli ajendatud optimistlikest uuendustest ja keerukatest konfliktide lahendamise strateegiatest nagu OT.
- Projektijuhtimise tarkvara (nt Asana, Jira): Ülesannete olekute uuendamine, kasutajate määramine ja ülesannete kommenteerimine kasutavad sageli optimistlikke uuendusi.
- Pangandus- ja finantsrakendused: Kuigi turvalisus on esmatähtis, kasutavad kasutajaliidesed sageli optimistlikke uuendusi teatud toimingute jaoks, näiteks rahaülekannete tegemiseks või kontojääkide vaatamiseks. Selliste rakenduste turvamisel tuleb aga olla hoolikas.
Selles postituses käsitletud kontseptsioonid kehtivad globaalselt. Optimistlike uuenduste, konfliktide lahendamise ja `useOptimistic` konksu põhimõtteid saab rakendada veebirakendustele olenemata kasutaja geograafilisest asukohast, kultuurilisest taustast või tehnoloogilisest infrastruktuurist. Võti peitub läbimõeldud disainis ja teie rakenduse nõuetele kohandatud tõhusas ühendamisloogikas.
Kokkuvõte
Optimistlike uuenduste ja konfliktide lahendamise valdamine on reageerivate ja kaasahaaravate kasutajaliideste loomisel ülioluline. Reacti `useOptimistic` konks pakub selle rakendamiseks võimsat ja paindlikku tööriista. Mõistes põhikontseptsioone ja rakendades selles juhendis käsitletud tehnikaid, saate oma veebirakenduste kasutajakogemust oluliselt parandada. Pidage meeles, et sobiva ühendamisloogika valik sõltub teie rakenduse eripäradest, seega on oluline valida oma konkreetsetele vajadustele sobiv lähenemine.
Hoolikalt optimistlike uuenduste väljakutsetega tegeledes ja neid parimaid praktikaid rakendades saate luua oma globaalsele publikule dünaamilisemaid, kiiremaid ja rahuldustpakkuvamaid kasutajakogemusi. Pidev õppimine ja katsetamine on optimistliku kasutajaliidese ja konfliktide lahendamise maailmas edukalt navigeerimise võti. Võime luua reageerivaid kasutajaliideseid, mis tunduvad hetkelised, eristab teie rakendusi teistest.